uniform sampler2DShadow depthMap;   //! shadow map for all lights
uniform mat4 lproj;                 //! light projection matrix
uniform mat4 camIMV;                //! inverse of camera modelview matrix
uniform sampler2D lights;           //! texture container for light directions

varying vec3 normal, lightVec, viewerVec; //! normal vector for fragment
                                          //! light vector
                                          //! viewer vector

varying vec4 texCoord;                    //! fragment coordinates
varying mat4 modelViewMat;                //! modelViewMatrix

//////////////////////////////////////////////////////////////////////////////////
///////// IF "TODO" CHECK RETURNED TRUE THAN SHADER SHOULD BE WORKING OK /////////
//////////////////////////////////////////////////////////////////////////////////

mat4 lookAt( vec3 eyev, vec3 centerv, vec3 upv )
{
	vec3 m_eye = eyev;
	vec3 m_center = centerv;
	vec3 m_up = upv;

	vec3 look = m_center - m_eye;
	look = normalize(look);

	vec3 side = cross(look, m_up);
	side = normalize(side);

	vec3 up = cross(side, look);

	mat4 tempMatrix = mat4( side.x, up.x, -look.x, 0,
		                    side.y, up.y, -look.y, 0,
			                side.z, up.z, -look.z, 0,
						         0,   0,    0,     1 );

	mat4 translationMat = mat4( 1,   0,      0,      0,
		                        0,   1,      0,      0,
								0,   0,      1,      0,
						        -m_eye.x,   -m_eye.y,      -m_eye.z,          1 );
						    
	mat4 final = tempMatrix * translationMat;
	
	return (tempMatrix * translationMat);
}

void main()
{
	vec4 I, Id, Is, shadowCoord, Ia;
	vec3 n, lv, rv, vv, lightV;
	float NdotL, RdotV, power;
	vec2 coords;
	float shadow;
	mat4 transform, lightMV, temp;
	
	//! Bias matrix (translate and scale by 0.5)
	mat4 bias = mat4( 0.5, 0.0, 0.0, 0.0,
	              0.0, 0.5, 0.0, 0.0,
	              0.0, 0.0, 0.5, 0.0,
	              0.5, 0.5, 0.5, 1.0 );
	              
	temp = bias * lproj;
	
	n = normalize(normal);
	vv = normalize( viewerVec );

	I = vec4( 0.0, 0.0, 0.0, 0.0 );
	
	Ia = vec4(0.2, 0.2, 0.2, 0.0);
	
	//! Iterate through lights and calculate color of pixel lighted by every light.
	//! lighting
	for( int i = 0; i < 1; ++i )
	{
		for( int j = 0; j < 1; ++j )
		{
			float x = float(i);
			float y = float(j);

			coords = vec2(x/32.0, y/32.0);
			lightV = vec3( texture2D( lights, coords ) );
			lightV = (lightV * 2.0) - 1.0;
				
			lv = lightV;			
			NdotL = max(dot(n,lv),0.0);	
			rv = 2.0 * NdotL * n - lv;

			Id = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse * NdotL;
			Is = gl_FrontMaterial.specular * gl_LightSource[0].specular * pow( max( dot(rv, vv), 0.0), gl_FrontMaterial.shininess );
			I += Id + Is + Ia;	
			
			
			/*lightMV = lookAt( vec3(lightV*10.0), vec3(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0) );
			
			transform = temp * lightMV * camIMV * modelViewMat;
			shadowCoord = transform * texCoord;
			shadowCoord.x /= 8.0; shadowCoord.y /= 8.0;
			
			shadow = shadow2DProj(depthMap, shadowCoord).r;
			
			if(shadow < (shadowCoord.z/25.0 - 0.0) )// -( 2.0/25.0) )
				shadow = 0.3;
			else
				shadow = 1.0;
				
			I = I * shadow;	*/
		}
	}

	//I.r /= 36.0; I.g /= 36.0; I.b /= 36.0;
	//! shadowing
	for( int i = 0; i < 1; ++i )
	{
		for( int j = 0; j < 1; ++j )
		{	
			float x = float(i);
			float y = float(j);

			coords = vec2(x/32.0, y/32.0);//vec2( x/16.0, y/8.0);
			lightV = vec3( texture2D( lights, coords ) );
			lightV = (lightV * 2.0) - 1.0;		
		
			lightMV = lookAt( vec3(lightV*10.0), vec3(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0) );
			
			transform = temp * lightMV * camIMV * modelViewMat;
			shadowCoord = transform * texCoord;
			shadowCoord.x /= 8.0; shadowCoord.y /= 8.0;
			
			shadow = shadow2DProj(depthMap, shadowCoord).r;
			
			if(shadow < (shadowCoord.z/25.0) )// && lightV.z >=0.0 && lightV.y >= 0.0 )
				shadow = 0.3;
			else
				shadow = 1.0;
				
			I = I * shadow;		
		}
	}
	//I.r /= 2.0; I.g /= 2.0; I.b /= 2.0;
	//I.r /= 36.0; I.g /= 36.0; I.b /= 36.0;
	gl_FragColor = I;
}

	//lightMV[0][0] = 0.98058063;
	//lightMV[0][1] = -0.13730876;
	//lightMV[0][2] = 0.14002801;
	//lightMV[0][3] = 0.0;
	//
	//lightMV[1][0] = 0.0;
	//lightMV[1][1] = 0.71400553;
	//lightMV[1][2] = 0.70014006;
	//lightMV[1][3] =	0.0;
	//
	//lightMV[2][0] = -0.19611613;
	//lightMV[2][1] = -0.68654376;
	//lightMV[2][2] = 0.70014006;
	//lightMV[2][3] =	0.0;
	//
	//lightMV[3][0] = 0.000000062597394;
	//lightMV[3][1] = 0.00000010432899;
	//lightMV[3][2] = -10.0;
	//lightMV[3][3] =	1.0;	